<template>
  <div class="trend-chart-container">
    <div class="chart-header">
      <el-icon class="chart-icon">
        <Monitor />
      </el-icon>
      <span class="chart-title">趋势图</span>
      <span v-if="villageName" class="chart-subtitle">{{ villageName }}</span>
      <span v-if="modelName" class="chart-subtitle">{{ modelName }}</span>
      <el-tag type="success" size="small" class="chart-tag">{{ dataPointsCount }} 个数据点</el-tag>
      
      <div class="header-actions">
        <el-button 
          link 
          type="primary" 
          size="small"
          @click="exportToExcel"
          class="export-btn"
        >
          📊 导出Excel
        </el-button>
        <el-divider direction="vertical" />
        <el-button 
          link 
          type="primary" 
          size="small"
          @click="exportToPDF"
          class="export-btn"
        >
          📄 导出PDF
        </el-button>
      </div>
    </div>
    
    <div class="chart-content">
      <div ref="chartRef" class="chart-canvas"></div>
    </div>
    
    <div class="chart-info">
      <div v-if="villageName" class="info-item">
        <span class="label">小区:</span>
        <span class="value">{{ villageName }}</span>
      </div>
      <div v-if="modelName" class="info-item">
        <span class="label">位点:</span>
        <span class="value">{{ modelName }}</span>
      </div>
      <div class="info-item">
        <span class="label">数据范围:</span>
        <span class="value">{{ formatTimeRange() }}</span>
      </div>
      <div class="info-item">
        <span class="label">最大值:</span>
        <span class="value">{{ maxValue }}</span>
      </div>
      <div class="info-item">
        <span class="label">最小值:</span>
        <span class="value">{{ minValue }}</span>
      </div>
      <div class="info-item">
        <span class="label">平均值:</span>
        <span class="value">{{ avgValue }}</span>
      </div>
    </div>
  </div>
</template>

<script setup>
import { ref, onMounted, computed, watch } from 'vue'
import { Monitor } from '@element-plus/icons-vue'
import { ElMessage } from 'element-plus'

const props = defineProps({
  timestamps: {
    type: Array,
    required: true
  },
  values: {
    type: Array,
    required: true
  },
  dataPointsCount: {
    type: Number,
    default: 0
  },
  villageName: {
    type: String,
    default: null
  },
  modelName: {
    type: String,
    default: null
  },
  modelId: {
    type: String,
    default: null
  }
})

const chartRef = ref(null)
let chart = null
const exporting = ref(null)

// 规范化数值数组
const normalizeValues = (values) => {
  return values.map(v => {
    const num = typeof v === 'number' ? v : parseFloat(v)
    return isNaN(num) ? 0 : num
  })
}

// 计算统计值
const maxValue = computed(() => {
  if (props.values.length === 0) return '—'
  const normalized = normalizeValues(props.values)
  return Math.max(...normalized).toFixed(2)
})

const minValue = computed(() => {
  if (props.values.length === 0) return '—'
  const normalized = normalizeValues(props.values)
  return Math.min(...normalized).toFixed(2)
})

const avgValue = computed(() => {
  if (props.values.length === 0) return '—'
  const normalized = normalizeValues(props.values)
  const sum = normalized.reduce((a, b) => a + b, 0)
  return (sum / normalized.length).toFixed(2)
})

// 格式化时间范围（不显示年份）
const formatTimeRange = () => {
  if (props.timestamps.length < 2) return '—'
  const start = props.timestamps[0]
  const end = props.timestamps[props.timestamps.length - 1]
  
  // 提取日期和时间，去掉年份
  const formatTimestamp = (timestamp) => {
    const parts = timestamp.split(' ')
    const date = parts[0] // YYYY-MM-DD
    const time = parts[1] || '' // HH:mm:ss
    
    // 去掉年份：YYYY-MM-DD -> MM-DD
    const dateParts = date.split('-')
    if (dateParts.length === 3) {
      return `${dateParts[1]}-${dateParts[2]} ${time}`.trim()
    }
    return timestamp
  }
  
  const startFormatted = formatTimestamp(start)
  const endFormatted = formatTimestamp(end)
  const startDate = start.split(' ')[0]
  const endDate = end.split(' ')[0]
  
  // 如果在同一天，只显示日期和时间范围
  if (startDate === endDate) {
    const time1 = start.split(' ')[1]
    const time2 = end.split(' ')[1]
    return `${startDate.slice(5)} ${time1} ~ ${time2}`
  }
  
  // 如果跨多天，显示日期和时间
  return `${startFormatted} ~ ${endFormatted}`
}

// 格式化时间轴标签（不显示年份）
const formatAxisLabel = (timestamp) => {
  if (!timestamp) return ''
  const parts = timestamp.split(' ')
  const date = parts[0] // YYYY-MM-DD
  const time = parts[1] || '' // HH:mm:ss
  
  // 去掉年份：YYYY-MM-DD -> MM-DD
  const dateParts = date.split('-')
  if (dateParts.length === 3) {
    return `${dateParts[1]}-${dateParts[2]} ${time}`.trim()
  }
  return timestamp
}

// 数据采样优化 - 当数据点过多时进行采样
const getSampledData = () => {
  const maxDataPoints = 150 // 最多显示150个数据点
  const totalPoints = props.timestamps.length
  
  // 确保值是数字类型
  const normalizedValues = normalizeValues(props.values)
  
  if (totalPoints <= maxDataPoints) {
    return {
      timestamps: props.timestamps,
      values: normalizedValues,
      samplingRate: 1
    }
  }
  
  // 计算采样率
  const samplingRate = Math.ceil(totalPoints / maxDataPoints)
  const sampledTimestamps = []
  const sampledValues = []
  
  for (let i = 0; i < totalPoints; i += samplingRate) {
    sampledTimestamps.push(props.timestamps[i])
    sampledValues.push(normalizedValues[i])
  }
  
  // 确保最后一个点被包含
  if (sampledTimestamps[sampledTimestamps.length - 1] !== props.timestamps[totalPoints - 1]) {
    sampledTimestamps.push(props.timestamps[totalPoints - 1])
    sampledValues.push(normalizedValues[totalPoints - 1])
  }
  
  return {
    timestamps: sampledTimestamps,
    values: sampledValues,
    samplingRate
  }
}

// 初始化图表
const initChart = () => {
  // 动态导入 echarts
  import('echarts').then((echartsModule) => {
    const echarts = echartsModule.default || echartsModule
    
    if (chartRef.value) {
      // 销毁旧图表
      if (chart) {
        chart.dispose()
      }
      
      // 创建新图表
      chart = echarts.init(chartRef.value, null, { locale: 'ZH' })
      
      // 获取采样后的数据
      const { timestamps, values } = getSampledData()
      
      // 配置图表选项
      const option = {
        title: {
          text: '',
          left: 'center'
        },
        tooltip: {
          trigger: 'axis',
          backgroundColor: 'rgba(32, 33, 36, 0.95)',
          borderColor: '#555',
          textStyle: {
            color: '#fff'
          },
          formatter: function (params) {
            if (params.length > 0) {
              const param = params[0]
              const value = typeof param.value === 'number' ? param.value : parseFloat(param.value)
              return `
                <div style="padding: 8px;">
                  <div style="color: #bbb; font-size: 12px; margin-bottom: 4px;">${timestamps[param.dataIndex]}</div>
                  <div style="color: #fff;">
                    <span style="color: #5470c6;">●</span>
                    <span>${isNaN(value) ? param.value : value.toFixed(2)}</span>
                  </div>
                </div>
              `
            }
            return ''
          }
        },
        grid: {
          left: '10%',
          right: '10%',
          top: '10%',
          bottom: '20%',
          containLabel: true
        },
        xAxis: {
          type: 'category',
          boundaryGap: false,
          data: timestamps.map((timestamp, idx) => {
            // 动态计算标签显示间隔
            const labelInterval = Math.max(1, Math.floor(timestamps.length / 8))
            return idx % labelInterval === 0 ? formatAxisLabel(timestamp) : ''
          }),
          axisLine: {
            lineStyle: {
              color: '#ccc'
            }
          },
          axisLabel: {
            color: '#999',
            fontSize: 11,
            rotate: 45
          }
        },
        yAxis: {
          type: 'value',
          name: '数值',
          axisLine: {
            lineStyle: {
              color: '#ccc'
            }
          },
          splitLine: {
            lineStyle: {
              color: '#e8e8e8'
            }
          },
          axisLabel: {
            color: '#999'
          }
        },
        series: [
          {
            data: values,
            type: 'line',
            smooth: true,
            symbol: 'none', // 隐藏数据点符号以提高性能
            symbolSize: 4,
            itemStyle: {
              color: '#5470c6'
            },
            lineStyle: {
              color: '#5470c6',
              width: 2
            },
            areaStyle: {
              color: 'rgba(84, 112, 198, 0.1)'
            },
            emphasis: {
              symbol: 'circle', // hover时显示符号
              itemStyle: {
                borderColor: '#5470c6',
                borderWidth: 2
              }
            }
          }
        ]
      }
      
      // 设置图表选项
      chart.setOption(option, true)
      
      // 响应式处理 - 使用防抖避免频繁resize
      let resizeTimer
      const handleResize = () => {
        clearTimeout(resizeTimer)
        resizeTimer = setTimeout(() => {
          if (chart) {
            chart.resize()
          }
        }, 300)
      }
      
      window.addEventListener('resize', handleResize)
    }
  }).catch(err => {
    console.error('动态加载 echarts 失败:', err)
  })
}

// 监听数据变化
watch(
  () => [props.timestamps, props.values],
  () => {
    if (props.timestamps.length > 0 && props.values.length > 0) {
      initChart()
    }
  },
  { deep: true }
)

// 导出为 Excel
const exportToExcel = () => {
  exporting.value = 'excel'
  try {
    import('xlsx').then((xlsxModule) => {
      const XLSX = xlsxModule.default || xlsxModule
      
      // 构建数据 - 使用完整原始数据，不采样
      const data = [
        ['时间', '数值'],
        ...props.timestamps.map((time, idx) => [time, props.values[idx].toFixed(2)])
      ]
      
      // 创建工作表
      const ws = XLSX.utils.aoa_to_sheet(data)
      
      // 设置列宽
      ws['!cols'] = [{ wch: 25 }, { wch: 15 }]
      
      // 创建工作簿
      const wb = XLSX.utils.book_new()
      XLSX.utils.book_append_sheet(wb, ws, '趋势数据')
      
      // 导出文件
      const fileName = `趋势数据_${new Date().toISOString().slice(0, 10)}.xlsx`
      XLSX.writeFile(wb, fileName)
      
      ElMessage.success('Excel 导出成功')
    }).catch(err => {
      console.error('导入 xlsx 库失败:', err)
      ElMessage.error('导出失败，请检查网络连接')
    }).finally(() => {
      exporting.value = null
    })
  } catch (e) {
    console.error('导出 Excel 失败:', e)
    ElMessage.error('导出失败')
    exporting.value = null
  }
}

// 导出为 PDF
const exportToPDF = () => {
  exporting.value = 'pdf'
  try {
    Promise.all([
      import('html2canvas'),
      import('jspdf')
    ]).then(([html2canvasModule, jsPDFModule]) => {
      const html2canvas = html2canvasModule.default || html2canvasModule
      const jsPDF = jsPDFModule.default || jsPDFModule
      
      if (!chart || !chartRef.value) {
        ElMessage.error('图表未初始化')
        return
      }
      
      // 创建临时容器，用于生成报告HTML
      const tempContainer = document.createElement('div')
      tempContainer.style.position = 'absolute'
      tempContainer.style.left = '-9999px'
      tempContainer.style.width = '800px'
      tempContainer.style.backgroundColor = '#fff'
      tempContainer.style.padding = '20px'
      tempContainer.style.fontFamily = 'Arial, sans-serif'
      
      // 生成HTML报告内容
      const chartImage = chart.getDataURL({ type: 'png', pixelRatio: 2, backgroundColor: '#fff' })
      const reportTime = new Date().toLocaleString('zh-CN')
      const timeRange = formatTimeRange()
      
      tempContainer.innerHTML = `
        <div style="text-align: center; margin-bottom: 20px;">
          <h1 style="margin: 0 0 10px 0; font-size: 24px;">趋势数据分析报告</h1>
          <p style="margin: 0; color: #666; font-size: 12px;">生成于 ${reportTime}</p>
        </div>
        
        <div style="margin-bottom: 20px; padding: 15px; background: #f5f5f5; border-radius: 4px;">
          <div style="display: grid; grid-template-columns: 1fr 1fr; gap: 15px; font-size: 12px;">
            <div><strong>数据点数:</strong> ${props.dataPointsCount}</div>
            <div><strong>时间范围:</strong> ${timeRange}</div>
            <div><strong>最大值:</strong> ${maxValue.value}</div>
            <div><strong>最小值:</strong> ${minValue.value}</div>
            <div><strong>平均值:</strong> ${avgValue.value}</div>
          </div>
        </div>
        
        <div style="margin-bottom: 20px; text-align: center;">
          <img src="${chartImage}" style="width: 100%; max-width: 700px; border: 1px solid #ddd; border-radius: 4px;" />
        </div>
        
        <div style="margin-top: 20px;">
          <h3 style="margin: 0 0 10px 0; font-size: 14px;">数据详情（前50条）</h3>
          <table style="width: 100%; border-collapse: collapse; font-size: 11px;">
            <thead>
              <tr style="background: #409eff; color: white;">
                <th style="padding: 8px; text-align: left; border: 1px solid #ddd;">时间</th>
                <th style="padding: 8px; text-align: right; border: 1px solid #ddd;">数值</th>
              </tr>
            </thead>
            <tbody>
              ${props.timestamps.slice(0, 50).map((time, idx) => `
                <tr style="background: ${idx % 2 === 0 ? '#f9f9f9' : '#fff'};">
                  <td style="padding: 6px; border: 1px solid #ddd;">${time}</td>
                  <td style="padding: 6px; border: 1px solid #ddd; text-align: right;">${props.values[idx].toFixed(2)}</td>
                </tr>
              `).join('')}
            </tbody>
          </table>
        </div>
      `
      
      document.body.appendChild(tempContainer)
      
      // 将HTML转为canvas，然后转为PDF
      html2canvas(tempContainer, {
        scale: 2,
        backgroundColor: '#fff',
        logging: false,
        useCORS: true
      }).then(canvas => {
        // 计算 PDF 尺寸
        const pdf = new jsPDF('p', 'mm', 'a4')
        const pageWidth = pdf.internal.pageSize.getWidth()
        const pageHeight = pdf.internal.pageSize.getHeight()
        const imgWidth = pageWidth - 10
        const imgHeight = (imgWidth * canvas.height) / canvas.width
        
        let yPosition = 5
        let remainingHeight = imgHeight
        
        // 转换canvas为图片
        const imgData = canvas.toDataURL('image/png')
        const totalHeight = imgHeight
        let position = 0
        
        // 处理多页情况
        while (position < totalHeight) {
          const pageCanvasHeight = Math.min(pageHeight - 10, totalHeight - position)
          const sourceY = position * (canvas.height / totalHeight)
          const sourceHeight = (pageCanvasHeight / totalHeight) * canvas.height
          
          // 创建临时canvas来截取页面内容
          const pageCanvas = document.createElement('canvas')
          pageCanvas.width = canvas.width
          pageCanvas.height = sourceHeight
          const ctx = pageCanvas.getContext('2d')
          ctx.drawImage(canvas, 0, sourceY, canvas.width, sourceHeight, 0, 0, canvas.width, sourceHeight)
          
          const pageImgData = pageCanvas.toDataURL('image/png')
          
          if (position > 0) {
            pdf.addPage()
          }
          
          pdf.addImage(pageImgData, 'PNG', 5, 5, imgWidth, pageCanvasHeight)
          position += pageCanvasHeight
        }
        
        // 保存 PDF
        const fileName = `趋势数据_${new Date().toISOString().slice(0, 10)}.pdf`
        pdf.save(fileName)
        
        // 清理临时容器
        document.body.removeChild(tempContainer)
        
        ElMessage.success('PDF 导出成功')
        exporting.value = null
      }).catch(err => {
        console.error('HTML转PDF失败:', err)
        document.body.removeChild(tempContainer)
        ElMessage.error('导出失败')
        exporting.value = null
      })
    }).catch(err => {
      console.error('导入库失败:', err)
      ElMessage.error('导出失败，请检查网络连接')
      exporting.value = null
    })
  } catch (e) {
    console.error('导出 PDF 失败:', e)
    ElMessage.error('导出失败')
    exporting.value = null
  }
}

// 组件挂载时初始化
onMounted(() => {
  if (props.timestamps.length > 0 && props.values.length > 0) {
    initChart()
  }
})
</script>

<style scoped>
.trend-chart-container {
  background: var(--el-bg-color);
  border: 1px solid var(--el-border-color-light);
  border-radius: 0.5rem;
  padding: 1rem;
  margin: 0.5rem 0;
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
}

.chart-header {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  margin-bottom: 1rem;
  padding-bottom: 0.75rem;
  border-bottom: 2px solid var(--el-fill-color-light);
}

.chart-icon {
  color: var(--el-color-primary);
  font-size: 1.25rem;
  flex-shrink: 0;
}

.chart-title {
  font-weight: 600;
  color: var(--el-text-color-primary);
  font-size: 1rem;
}

.chart-subtitle {
  font-size: 0.875rem;
  color: var(--el-text-color-secondary);
  margin-left: 0.5rem;
  padding: 0 0.5rem;
  border-left: 2px solid var(--el-border-color-light);
  flex-shrink: 0;
}

.chart-tag {
  flex-shrink: 0;
}

.header-actions {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  margin-left: auto;
  flex-shrink: 0;
}

.export-btn {
  white-space: nowrap;
  font-size: 0.8125rem;
}

.chart-content {
  width: 100%;
  height: 300px;
  margin-bottom: 1rem;
  border-radius: 0.375rem;
  overflow: hidden;
  background: var(--el-bg-color-page);
}

.chart-canvas {
  width: 100%;
  height: 100%;
}

.chart-info {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
  gap: 1rem;
  padding: 0.75rem;
  background: var(--el-bg-color-page);
  border-radius: 0.375rem;
}

.info-item {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 0.5rem;
  border-radius: 0.25rem;
  background: var(--el-bg-color);
  border: 1px solid var(--el-fill-color-light);
}

.info-item .label {
  color: var(--el-text-color-secondary);
  font-size: 0.875rem;
  font-weight: 500;
}

.info-item .value {
  color: var(--el-text-color-primary);
  font-size: 0.9375rem;
  font-weight: 600;
  font-family: 'Courier New', monospace;
}

@media (max-width: 768px) {
  .trend-chart-container {
    padding: 0.75rem;
  }

  .chart-content {
    height: 200px;
    margin-bottom: 0.75rem;
  }

  .chart-info {
    grid-template-columns: repeat(2, 1fr);
    gap: 0.5rem;
  }

  .info-item {
    padding: 0.375rem;
  }

  .info-item .label {
    font-size: 0.75rem;
  }

  .info-item .value {
    font-size: 0.8125rem;
  }
}
</style>

